package com.yc.cloud.common.oss.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

/**
 * 点云数据工具类
 */
@Slf4j
public class PointCloudUtils {

    public static final String POINT_CLOUD_LAZ_SUFFIX = "laz";
    public static final String POINT_CLOUD_LAS_SUFFIX = "las";
    public static final String POINT_CLOUD_PLY_SUFFIX = "ply";
    public static final String CAMERA_GOSLAM_SUFFIX = "txt";
    public static final String CAMERA_NAVVIS_SUFFIX = "csv";
    public static final List<String> POINT_CLOUD_SUFFIX = Arrays.asList("laz", "las", "ply");
    //    public static final String LAS_INFO = "lasinfo64";
//    public static final String PDAL_URL = "http://192.168.2.4:7001/pdal/ply2las";

    /**
     * las文件转换
     *
     * @param poTreeConverterPath 转换引擎
     * @param lasPath             las文件地址
     * @param dstFolder           生成目录
     * @return
     */
    public static boolean lasConvert(String padlUrl, String poTreeConverterPath, String lasPath, String dstFolder) {
        log.info("lasConvert start...");
        Properties props = System.getProperties();
        String systemName = props.getProperty("os.name");
        System.out.println("系统:" + systemName);
        boolean flag = false;
        long start = System.currentTimeMillis();
        if (systemName.toLowerCase().contains("mac")) {
            flag = convertLasByDocker(padlUrl, lasPath, dstFolder);
        } else {
            List<String> commands = new ArrayList<>();
            commands.add(poTreeConverterPath);
            commands.add(lasPath);
            commands.add("-o");
            commands.add(dstFolder);
            flag = processCommands(commands);
        }
        log.info("lasConvert end...");
        log.info("lasConvert spend times :{}", System.currentTimeMillis() - start);
        return flag;
    }

    public static boolean repairBoundBox(String LAS_INFO, String lasPath) {
        List<String> commands = new ArrayList<>();
        commands.add(LAS_INFO);
        commands.add("-i");
        commands.add(lasPath);
        commands.add("-repair_bb");
        long start = System.currentTimeMillis();
        boolean flag = processCommands(commands);
        log.info("repairBoundBox spend times :" + (System.currentTimeMillis() - start));
        return flag;
    }


    public static boolean ply2las(String srcPlyPath, String dstLasPath) {
        //docker exec -it pdal_container pdal translate -i /app/data/input.ply -o /app/data/output.las
        List<String> commands = new ArrayList<>();
//        commands.add("docker");
//        commands.add("exec");
//        commands.add("-i");
//        commands.add("pdal");
        commands.add("pdal");
        commands.add("translate");
        commands.add("-i");
        commands.add(srcPlyPath);
        commands.add("-o");
        commands.add(dstLasPath);
        long start = System.currentTimeMillis();
        boolean flag = processCommands(commands);
        log.info("ply2las spend times :" + (System.currentTimeMillis() - start));
        return flag;
    }

    public static boolean ply2lasByDocker(String pdalUrl, String srcPlyPath, String dstLasPath) {

        var url = pdalUrl + "/ply2las";
        HttpRequest request = HttpRequest.post(url);
        log.info("ply2lasByDocker url: {}", url);
        // 创建 JSON 对象作为请求体
        JSONObject jsonBody = new JSONObject();
        jsonBody.putOpt("plyPath", srcPlyPath);
        jsonBody.putOpt("lasPath", dstLasPath);

        // 设置请求体和内容类型
        request.body(jsonBody.toString()); // 使用 JSON 字符串作为请求体
        request.header("Content-Type", "application/json; charset=UTF-8");

        try (HttpResponse response = request.execute()) {
            if (response.isOk()) {
                String result = response.body();
                log.info("ply2lasByDocker result: {}", result);
                if (StrUtil.isNotEmpty(result) && "true".equals(result)) {
                    return true;
                }
            }
        } catch (Exception e) {
            log.error("ply2lasByDocker An unexpected error occurred: {}", e.getMessage(), e);
        }
        return false;

    }


    public static boolean convertLasByDocker(String pdalUrl, String lasPath, String dstFolder) {

        HttpRequest request = HttpRequest.post(pdalUrl + "/convertLas");

        // 创建 JSON 对象作为请求体
        JSONObject jsonBody = new JSONObject();
        jsonBody.putOpt("lasPath", lasPath);
        jsonBody.putOpt("dstFolder", dstFolder);

        // 设置请求体和内容类型
        request.body(jsonBody.toString()); // 使用 JSON 字符串作为请求体
        request.header("Content-Type", "application/json; charset=UTF-8");

        // 发送请求并获取响应
        try (HttpResponse response = request.execute()) {
            if (response.isOk()) {
                String result = response.body();
                if (StrUtil.isNotEmpty(result) && "true".equals(result)) {
                    return true;
                }
            }
            return false;
        }
    }

    private static boolean processCommands(List<String> commands) {
        // System.out.println("commands=" + commands.replaceAll(",", ""););
        val stringBuilder = new StringBuilder();
        for (String command : commands) {
            stringBuilder.append(command).append(" ");
        }
        log.info(stringBuilder.toString());
        ProcessBuilder builder = new ProcessBuilder();
        builder.command(commands);
        return processOperation(builder);
    }

    private static boolean processOperation(ProcessBuilder builder) {
        InputStream error = null;
        InputStream is = null;
        try {
            val process = builder.start();
            //process.waitFor();//等待进程执行完毕
            //防止ffmpeg进程塞满缓存造成死锁
            error = process.getErrorStream();
            is = process.getInputStream();
            byte[] b = new byte[1024];
            int readbytes = -1;
            while ((readbytes = error.read(b)) != -1) {
                System.out.println("点云错误信息：" + new String(b, 0, readbytes));
                // return  false;
            }
            while ((readbytes = is.read(b)) != -1) {
                System.out.println("点云处理信息：" + new String(b, 0, readbytes));
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
//        finally {
//            try {
//                if (error != null) {
//                    error.close();
//                }
//                if (is != null) {
//                    is.close();
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
        return true;
    }

}
